garmin_gpi: fix proximity alerts for large numbers of isolated waypoints
authormaz <blob@p0d.org>
Sat, 15 Aug 2015 11:58:06 +0000 (13:58 +0200)
committerRobert Lipe <robertlipe@gpsbabel.org>
Mon, 17 Aug 2015 03:43:39 +0000 (22:43 -0500)
Large waypoint lists are organized into blocks of at most
WAYPOINTS_PER_BLOCK (128) POIs in generated GPI files for performance
reasons.

It appears that at least on older Garmin Nuvi devices, proximity alerts
often do not work (they do not show up as Custom POIs) and POI lists get
mangled (even to the point of crashing the unit) when there are several
such blocks, particularly with large lists of isolated waypoints.

This problem is the result of wdata_check() which may leave empty
nodes in the tree after sorting waypoints. These nodes show up as empty
blocks in the output file and are not well handled by some devices.

Preventing wdata_compute_size() and wdata_write() from issuing empty
blocks solves the issue.

Fixes: 26840523d411 ("Add support for multiple POI lists to writer code.")
Signed-off-by: maz <blob@p0d.org>
gpsbabel/garmin_gpi.cc

index 17e18f79954dcd595777c2db43c24c659ec9a52d..cae6f1d42ef8d295d6013db559fcf1338a80635d 100644 (file)
@@ -883,7 +883,10 @@ static int
 wdata_compute_size(writer_data_t* data)
 {
   queue* elem, *tmp;
-  int res;
+  int res = 0;
+
+  if (QUEUE_EMPTY(&data->Q))
+    goto skip_empty_block; /* do not issue an empty block */
 
   res = 23;    /* bounds, ... of tag 0x80008 */
 
@@ -1009,6 +1012,8 @@ wdata_compute_size(writer_data_t* data)
     }
   }
 
+skip_empty_block:
+
   if (data->top_left) {
     res += wdata_compute_size(data->top_left);
   }
@@ -1024,6 +1029,9 @@ wdata_compute_size(writer_data_t* data)
 
   data->sz = res;
 
+  if (QUEUE_EMPTY(&data->Q))
+    return res;
+
   return res + 12;     /* + 12 = caller needs info about tag header size */
 }
 
@@ -1033,6 +1041,9 @@ wdata_write(const writer_data_t* data)
 {
   queue* elem, *tmp;
 
+  if (QUEUE_EMPTY(&data->Q))
+    goto skip_empty_block; /* do not issue an empty block */
+
   gbfputint32(0x80008, fout);
   gbfputint32(data->sz, fout);
   gbfputint32(23, fout);       /* bounds + three bytes */
@@ -1155,6 +1166,8 @@ wdata_write(const writer_data_t* data)
     }
   }
 
+skip_empty_block:
+
   if (data->top_left) {
     wdata_write(data->top_left);
   }